﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Moonlite.ExtensionApi.ControlInterfaces;

namespace Moonlite.ExtensionApi
{
    public class ExtendedTreeView : TreeView
    {
        private Dictionary<Image, int> imageIndexMap = new Dictionary<Image, int>();
        private object lockObject = new object();
        private int osLevel = 0;
        private bool IsXPPlus
        {
            get { return OSLevel >= 510; }
        }

        private int OSLevel
        {
            get
            {
                lock (lockObject)
                {
                    if (osLevel == 0)
                    {
                        Version osVersion = Environment.OSVersion.Version;
                        if (osVersion.Major >= 6)
                        {
                            osLevel = 600;
                        }
                        else if (osVersion.Major == 5)
                        {
                            if (osVersion.Minor >= 2)
                            {
                                osLevel = 520;
                            }
                            else if (osVersion.Minor == 1)
                            {
                                osLevel = 510;
                            }
                            else
                            {
                                osLevel = 500;
                            }
                        }
                        else
                        {
                            osLevel = 1;
                        }
                    }

                    return osLevel;
                }
            }
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            if (IsXPPlus)
            {
                SafeNativeMethods.SetWindowTheme(Handle, "Explorer", null);
                if (Environment.OSVersion.Version.Major >= 6)
                {
                    uint flags = (uint)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TVM_GETEXTENDEDSTYLE, false, (int)IntPtr.Zero);
                    flags |= 0x0004;
                    UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TVM_SETEXTENDEDSTYLE, Convert.ToBoolean(flags), (int)flags);
                }
            }
        }

        private List<TreeNode> GetAllNodesCore(TreeNode node)
        {
            List<TreeNode> nodes = new List<TreeNode>();
            foreach (TreeNode childNode in node.Nodes)
            {
                nodes.Add(childNode);
                nodes.AddRange(GetAllNodesCore(childNode));
            }

            return nodes;
        }

        public TreeNode[] GetAllNodes()
        {
            List<TreeNode> nodes = new List<TreeNode>();
            foreach (TreeNode node in Nodes)
            {
                nodes.Add(node);
                nodes.AddRange(GetAllNodesCore(node));
            }

            return nodes.ToArray();
        }

        public TreeNode NodeFromHandle(IntPtr handle)
        {
            TreeNode[] nodes = GetAllNodes();
            foreach (TreeNode node in nodes)
            {
                if (node.Handle == handle)
                {
                    return node;
                }
            }

            return null;
        }

        public int GetImageIndexForImage(Image image)
        {
            if (!imageIndexMap.ContainsKey(image))
            {
                int index = ImageList.Images.Count;
                imageIndexMap.Add(image, index);
                ImageList.Images.Add(image);
            }

            return imageIndexMap[image];
        }

        protected override void OnAfterExpand(TreeViewEventArgs e)
        {
            base.OnAfterExpand(e);
            if (e.Node is AbstractCustomNode)
            {
                ((AbstractCustomNode)e.Node).Expanding();
            }
        }

        protected override void OnAfterCollapse(TreeViewEventArgs e)
        {
            base.OnAfterCollapse(e);
            if (e.Node is AbstractCustomNode)
            {
                ((AbstractCustomNode)e.Node).Collapsing();
            }
        }

        public ExtendedTreeView()
        {
            ShowLines = false;
        }
    }
}
